package com.tupu.service.impl.admin;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tupu.entity.admin.*;
import com.tupu.mapper.admin.*;
import com.tupu.service.admin.LabelService;
import com.tupu.util.FileUtil;
import com.tupu.util.LabelColorUtil;
import com.tupu.util.Neo4jUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class LabelServiceImpl extends ServiceImpl<LabelMapper, LabelInfo> implements LabelService {

    @Autowired(required = false)
    private KnowledgeListMapper knowledgeListMapper;

    @Autowired(required = false)
    private LabelMapper labelMapper;

    @Autowired(required = false)
    private PropertyMapper propertyMapper;

    @Autowired(required = false)
    private RelationMapper relationMapper;

    @Autowired(required = false)
    private RelationBuildingMapper relationBuildingMapper;

    @Autowired(required = false)
    private Neo4jUtil neo4jUtil;

    /**
     * 标签首页不分页
     *
     * @param node_id
     * @return
     */
    @Override
    public List<LabelInfo> listLabel(Long node_id) {
        List<LabelInfo> nodeLists = labelMapper.findGraphByNodeId(node_id);
        KnowledgeInfo knowledgeInfo = knowledgeListMapper.selectById(node_id);
        for (LabelInfo info : nodeLists) {
            info.setKnowledgeName(knowledgeInfo.getName());
        }
        return nodeLists;
    }

    /**
     * 修改标签颜色
     *
     * @param labelParam
     */
    @Override
    public void updateLabelColor(LabelVisualizedParam labelParam) {
        Long labelId = labelParam.getLabelId();
        String color = labelParam.getColor();
        LabelInfo label = new LabelInfo();
        label.setId(labelId);
        label.setColor(color);
        labelMapper.updateById(label);
    }

    /**
     * 删除标签及属性
     *
     * @param ids
     */
    @Override
    public void delByIds(List<Long> ids) {
        for (Long id : ids) {
            //删除标签
            labelMapper.deleteById(id);
            //删除属性
            propertyMapper.deleteByLabelId(id);
            //删除关系关联表数据
            relationBuildingMapper.deleteByLabelId(id);
        }
    }

    /**
     * 根据实例id 查询标签下所有属性
     *
     * @param case_id
     * @return
     */
    @Override
    public List<LabelPropertyInfo> findAttrsByName(Long case_id) {
        Long nodeId = null;
        String label_name = neo4jUtil.findByCaseId(case_id);
        List<Map<String, Object>> pros = neo4jUtil.findById(case_id);
        for (Map<String, Object> pro : pros) {
            for (String p : pro.keySet()) {
                if (p.equals("node_id")) {
                    Object obj = pro.get(p);
                    nodeId = Long.valueOf(String.valueOf(obj));
                }
            }
        }
        Long labelId = labelMapper.findIdByLabelNameAndNodeId(label_name, nodeId);
        List<LabelPropertyInfo> labelPropertyInfos = propertyMapper.findByLabelId(labelId);
        return labelPropertyInfos;
    }

    /**
     * 知识构建首页 标签列表，根据node_id关联首页图谱列表 可视化
     *
     * @param node_id
     * @return
     */
    @Override
    public LabelVisualized findByNodeIdVis(Long node_id) {
        List<LabelInfo> nodeLists = labelMapper.findGraphByNodeId(node_id);
        LabelVisualized lv = new LabelVisualized();
        List<Map<String, Object>> nodeList = new ArrayList<>();
        List<Map<String, Object>> linkList = new ArrayList<>();
        for (LabelInfo label : nodeLists) {
            lv.setRootId(label.getNodeId());
            lv.setLinks(linkList);
            Map<String, Object> nodeMap = new HashMap<>();
            nodeMap.put("id", label.getId().toString());
            nodeMap.put("color", label.getColor());
            nodeMap.put("borderWidth", "black");
            nodeMap.put("fontColor", "0");
            nodeMap.put("text", label.getLabel());
            Map<String, Object> map = new HashMap<>();
            map.put("tag", "");
            nodeMap.put("data", map);
            nodeList.add(nodeMap);
            lv.setNodes(nodeList);
        }
        List<RelationBuildingInfo> buildingLists = relationBuildingMapper.findOneByNodeId(node_id);
        for (RelationBuildingInfo rb : buildingLists) {
            Map<String, Object> linkMap = new HashMap<>();
            linkMap.put("from", rb.getStartId().toString());
            linkMap.put("to", rb.getEndId().toString());
            linkMap.put("text", relationMapper.findRelationName(rb.getRelationId()));
            linkList.add(linkMap);
            lv.setLinks(linkList);
        }
        return lv;
    }

    /**
     * 通过本体id（label_id）查询关系数据
     *
     * @param ids
     * @return
     */
    @Override
    public List<LabelInfo> findList(List<Integer> ids) {
        List<LabelInfo> labelLists = labelMapper.selectBatchIds(ids);
        for (LabelInfo label : labelLists) {
            label.setKnowledgeName(knowledgeListMapper.selectById(label.getNodeId()).getName());
        }
        return labelLists;
    }

    /**
     * 根据本体名字搜索
     *
     * @param label
     * @return
     */
    @Override
    public List<LabelInfo> findByName(String label) {
        List<LabelInfo> list = new ArrayList<>();
        QueryWrapper<LabelInfo> queryWrapper = new QueryWrapper<>();
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(label)) {
            queryWrapper.like("label", label);
            LabelInfo labelList = labelMapper.selectOne(queryWrapper);
            list.add(labelList);
            return list;
        }
        return labelMapper.selectList(null);
    }

    /**
     * 删除标签，标签属性，关系关联表，节点，节点关系
     *
     * @param label_id
     * @param node_id
     */
    @Override
    public void del(Long label_id, Long node_id) {
        LabelInfo label = labelMapper.selectById(label_id);
        //删除标签
        labelMapper.deleteById(label_id);
        //删除属性
        propertyMapper.deleteByLabelId(label_id);
        //删除关系关联表
        relationBuildingMapper.deleteByLabelId(label_id);

        //删除实例、实例关系
        List<Long> idList = neo4jUtil.findAllByNodeIdAndLabel(node_id, label.getLabel());
        for (Long id : idList) {
            neo4jUtil.delNode(id);
        }
    }

    /**
     * 标签关系数据 分页
     *
     * @param node_id
     * @param name
     * @param page
     * @param size
     * @return
     */
    @Override
    public Page<RelationBuildingInfo> labelRelationDataManagement(Long node_id, String name, Long page, Long size) {
        //通过node_id 查询关系表数据
        QueryWrapper<RelationInfo> relationQueryWrapper = new QueryWrapper<>();
        relationQueryWrapper.eq("node_id", node_id);
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(name)) {
            relationQueryWrapper.like("name", name);
        }
        List<RelationInfo> relationLists = relationMapper.selectList(relationQueryWrapper);
        //返回具体关系数据
        QueryWrapper<RelationBuildingInfo> listQueryWrapper = new QueryWrapper<>();
        Page<RelationBuildingInfo> pageInfo = new Page<>(page, size);
        Long id = null;
        for (RelationInfo rela : relationLists) {
            id = rela.getId();
            listQueryWrapper.or().eq("relation_id", id);
            listQueryWrapper.orderByAsc("id");
            relationBuildingMapper.selectPage(pageInfo, listQueryWrapper);
            List<RelationBuildingInfo> records = pageInfo.getRecords();
            KnowledgeInfo knowledgeInfo = knowledgeListMapper.selectById(node_id);
            for (RelationBuildingInfo r : records) {
                r.setStartName(labelMapper.findlabelName(r.getStartId()));
                r.setEndName(labelMapper.findlabelName(r.getEndId()));
                r.setRelationName(relationMapper.findRelationName(r.getRelationId()));
                r.setKnowledgeName(knowledgeInfo.getName());
            }
        }
        return pageInfo;
    }

    /**
     * 本体、标签数据不分页
     *
     * @param node_id
     * @return
     */
    @Override
    public List<LabelInfo> labelDataManagementAll(Long node_id) {

        QueryWrapper<LabelInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("node_id", node_id);
        List<LabelInfo> labelLists = labelMapper.selectList(queryWrapper);
        KnowledgeInfo knowledgeInfo = knowledgeListMapper.selectById(node_id);
        for (LabelInfo label : labelLists) {
            Map<String, Object> map = new HashMap<>();
            List<LabelPropertyInfo> list = propertyMapper.findByLabelId(label.getId());
            for (LabelPropertyInfo pro : list) {
                map.put(pro.getName(), pro.getProId());
            }
            label.setAttrs(map);
            label.setKnowledgeName(knowledgeInfo.getName());
        }

        return labelLists;
    }

    /**
     * csv 导入关系及属性
     *
     * @param file_path
     * @param node_id
     * @return
     * @throws IOException
     */
    @Override
    public List<List<String>> addLabelAndProperty(String file_path, Long node_id) throws IOException {
        //Linux环境上传
        //file_path = ipAddress + file_path;
        File file = new File(file_path);
        InputStream inputStream;
        ClassPathResource resource = new ClassPathResource(file_path);
        inputStream = resource.getInputStream();
        FileUtils.copyInputStreamToFile(inputStream, file);
        String absolutePath = file.getAbsolutePath();
        //System.out.println("==========" + absolutePath);
        List<List<String>> lists = null;
        try {
            lists = FileUtil.readCsv(absolutePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
        }

        //本地环境上传
        //List<List<String>> lists = FileUtil.readCsv(file_path);

        List<Long> propertySum = new ArrayList<>();

        List<String> labelList = new ArrayList<>();
        for (List<String> s : lists) {
            String s1 = s.get(0);
            labelList.add(s1);

            int size = s.size();
            propertySum.add((long) (size - 1));
        }
        //插入标签
        for (int j = 0; j < lists.size(); j++) {
            LabelInfo label = new LabelInfo();
            label.setNodeId(Long.valueOf(node_id));
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String format = sdf.format(date);
            label.setUpdateTime(format);
            label.setLabel(labelList.get(j));

            //颜色
            List<String> colorList = LabelColorUtil.colorList();
            QueryWrapper<LabelInfo> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.eq("node_id", label.getNodeId());
            List<LabelInfo> labelLists = labelMapper.selectList(queryWrapper2);
            String color = "";
            if (null != labelLists) {
                for (LabelInfo l : labelLists) {
                    colorList.remove(l.getColor());
                }
            }
            if (null != colorList && colorList.size() > 0) {
                Random random = new Random();
                color = colorList.get(random.nextInt(colorList.size()));
            } else {
                color = LabelColorUtil.getColor();
            }
            label.setColor(color);
            labelMapper.insert(label);
            //插入属性
            Long id = label.getId();
            for (int l = 0; l < propertySum.get(j); l++) {
                LabelPropertyInfo pro = new LabelPropertyInfo();
                pro.setLabelId(id);
                pro.setName(lists.get(j).get(l + 1));
                propertyMapper.insert(pro);
            }
        }
        return lists;
    }

    /**
     * 标签列表，根据node_id关联首页图谱列表 标签模糊搜索,分页
     *
     * @param node_id
     * @param label
     * @param page
     * @param size
     * @return
     */
    @Override
    public Page<LabelInfo> pageCondition(Long node_id, String label, Integer page, Integer size) {
        QueryWrapper<LabelInfo> queryWrapper = new QueryWrapper<>();
        Page<LabelInfo> pageInfo = new Page<>(page, size);
        if (!StringUtils.isEmpty(node_id)) {
            queryWrapper.eq("node_id", node_id);
        }
        if (!StringUtils.isEmpty(label)) {
            queryWrapper.like("label", label);
        }
        labelMapper.selectPage(pageInfo, queryWrapper);

        List<LabelInfo> list = pageInfo.getRecords();
        for (LabelInfo info : list) {
            if (!StringUtils.isEmpty(node_id)) {
                KnowledgeInfo knowledgeInfo = knowledgeListMapper.selectById(node_id);
                info.setKnowledgeName(knowledgeInfo.getName());
            }
        }
        return pageInfo;
    }

    /**
     * 根据id更新标签及属性+实例、实例关系
     *
     * @param label
     */
    @Override
    public void updateLabelAndAttrsAndNode(LabelInfo label) {
        //日期
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String format = sdf.format(date);
        label.setUpdateTime(format);

        Long id = label.getId();
        Long nodeId = label.getNodeId();
        LabelInfo info = labelMapper.selectById(id);
        //节点id
        List<Long> ids = neo4jUtil.allIds(info.getLabel(), nodeId);
        Map<String, Object> newPros = label.getAttrs();
        newPros.remove("name");
        newPros.remove("uid");
        Map<String, Object> oldPros = new HashMap<>();
        QueryWrapper<LabelPropertyInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("label_id", id);
        List<LabelPropertyInfo> labelPropertyInfo2 = propertyMapper.selectList(wrapper);
        for (LabelPropertyInfo p : labelPropertyInfo2) {
            oldPros.put(p.getName(), p.getProId());
        }
        oldPros.remove("name");
        oldPros.remove("uid");
        List<Long> oldList = new ArrayList<>();
        List<Long> newList = new ArrayList<>();
        //新增
        for (Map.Entry<String, Object> entry : newPros.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value.toString().equals("") && !key.isEmpty()) {

                LabelPropertyInfo property = new LabelPropertyInfo();
                property.setName(key);
                property.setLabelId(id);
                propertyMapper.insert(property);
                // newPros.remove(entry.getKey());
            }
            if (!value.equals("")) {
                newList.add(Long.parseLong(String.valueOf(value)));
            }
        }

        for (Map.Entry<String, Object> entry : oldPros.entrySet()) {
            Object value = entry.getValue();
            oldList.add(Long.parseLong(String.valueOf(value)));
        }
        //删除
        List<Long> result = new ArrayList<>(oldList);
        result.removeAll(newList);
        if (!result.isEmpty()) {
            for (Object pro_id : result) {
                Long pId = Long.valueOf(pro_id.toString());
                LabelPropertyInfo property = propertyMapper.selectById(pId);
                neo4jUtil.delProperty(nodeId, info.getLabel(), property.getName());
                propertyMapper.deleteById(pId);
            }
        }
        //编辑更新
        for (Map.Entry<String, Object> entry : newPros.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (!value.equals("")) {
                //旧属性
                LabelPropertyInfo labelPropertyInfo = propertyMapper.selectById(Long.valueOf(String.valueOf(value)));
                String oldName = labelPropertyInfo.getName();
                try {
                    //通过id获取新属性
                    for (Long l : ids) {
                        //判断
                        if (!value.toString().equals(oldPros.get(key))) {
                            neo4jUtil.updateProperty(l, key, oldName);
                        }
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
                LabelPropertyInfo property = new LabelPropertyInfo();
                property.setLabelId(id);
                property.setName(key);
                property.setProId(Long.valueOf(String.valueOf(value)));
                propertyMapper.updateById(property);
            }
        }
        labelMapper.updateById(label);
        neo4jUtil.updateLabel(info.getLabel(), label.getLabel(), label.getNodeId());
    }

    /**
     * 通过标签id查找一条标签详情
     *
     * @param id
     * @return
     */
    @Override
    public LabelInfo findOne(Long id) {
        LabelInfo labelList = labelMapper.selectById(id);
        //属性
        Map<String, Object> property = new HashMap<>();
        QueryWrapper<LabelPropertyInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("label_id", id);
        List<LabelPropertyInfo> labelPropertyInfos = propertyMapper.selectList(queryWrapper);
        for (LabelPropertyInfo pro : labelPropertyInfos) {
            property.put(pro.getName(), pro.getProId());
        }
        labelList.setAttrs(property);
        return labelList;
    }

    /**
     * 新增标签,属性
     *
     * @param label
     */
    @Override
    public void addLabel(LabelInfo label) {
        //日期
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String format = sdf.format(date);
        label.setUpdateTime(format);
        //颜色
        List<String> colorList = LabelColorUtil.colorList();
        QueryWrapper<LabelInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("node_id", label.getNodeId());
        List<LabelInfo> labelLists = labelMapper.selectList(queryWrapper);
        String color = "";
        if (null != labelLists) {
            for (LabelInfo l : labelLists) {
                colorList.remove(l.getColor());
            }
        }
        if (null != colorList && colorList.size() > 0) {
            Random random = new Random();
            color = colorList.get(random.nextInt(colorList.size()));
        } else {
            color = LabelColorUtil.getColor();
        }
        label.setColor(color);
        labelMapper.insert(label);
        //属性表，判断属性是否为空
        Long id = label.getId();

        Map<String, Object> pros = label.getAttrs();
        pros.put("uid", "");
        pros.put("name", "");
        List<String> attrs = new ArrayList<>();
        for (Map.Entry<String, Object> entry : pros.entrySet()) {
            String key = entry.getKey();
            attrs.add(key);
        }
        while (attrs.remove("")) ;
        while (attrs.remove(" ")) ;
        while (attrs.remove(null)) ;
        if (attrs != null && !attrs.isEmpty()) {
            for (String property : attrs) {
                LabelPropertyInfo labelPropertyInfo = new LabelPropertyInfo();
                labelPropertyInfo.setLabelId(id);
                labelPropertyInfo.setName(property);
                propertyMapper.insert(labelPropertyInfo);
            }
        }
    }

    /**
     * 新增标签,属性（可视化）
     *
     * @param label
     * @return
     */
    @Override
    public LabelVisualized addLabelVis(LabelInfo label) {
        LabelVisualized labelVis = new LabelVisualized();
        //修改日期
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String format = sdf.format(date);
        label.setUpdateTime(format);
        //颜色
        List<String> colorList = LabelColorUtil.colorList();
        QueryWrapper<LabelInfo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("node_id", label.getNodeId());
        List<LabelInfo> labelLists = labelMapper.selectList(queryWrapper2);
        String color = "";
        if (null != labelLists) {
            for (LabelInfo l : labelLists) {
                colorList.remove(l.getColor());
            }
        }
        if (null != colorList && colorList.size() > 0) {
            Random random = new Random();
            color = colorList.get(random.nextInt(colorList.size()));
        } else {
            color = LabelColorUtil.getColor();
        }
        label.setColor(color);
        labelMapper.insert(label);
        //属性表，判断属性是否为空
        Long id = label.getId();

        Map<String, Object> pros = label.getAttrs();
        pros.put("uid", "");
        pros.put("name", "");
        List<String> attrs = new ArrayList<>();
        for (Map.Entry<String, Object> entry : pros.entrySet()) {
            String key = entry.getKey();
            attrs.add(key);
        }
        while (attrs.remove("")) ;
        while (attrs.remove(" ")) ;
        while (attrs.remove(null)) ;
        if (attrs != null && !attrs.isEmpty()) {
            for (String property : attrs) {
                LabelPropertyInfo labelPropertyInfo = new LabelPropertyInfo();
                labelPropertyInfo.setLabelId(id);
                labelPropertyInfo.setName(property);
                propertyMapper.insert(labelPropertyInfo);
            }
        }
        labelVis.setRootId(label.getNodeId());
        List<Map<String, Object>> nodeList = new ArrayList<>();
        Map<String, Object> nodeMap = new HashMap<>();
        nodeMap.put("id", id);
        nodeMap.put("color", color);
        nodeMap.put("borderWidth", "black");
        nodeMap.put("fontColor", "0");
        nodeMap.put("text", label.getLabel());
        Map<String, Object> map = new HashMap<>();
        map.put("tag", "");
        nodeMap.put("data", map);
        nodeList.add(nodeMap);
        labelVis.setNodes(nodeList);
        List<Map<String, Object>> linkList = new ArrayList<>();
        labelVis.setLinks(linkList);
        return labelVis;
    }

    /**
     * 知识管理-数据管理-本体、标签数据
     *
     * @param name
     * @param node_id
     * @param page
     * @param size
     * @return
     */
    @Override
    public Page<LabelInfo> labelDataManagement(String name, Long node_id, Long page, Long size) {
        QueryWrapper<LabelInfo> queryWrapper = new QueryWrapper<>();
        Page<LabelInfo> pageInfo = new Page<>(page, size);
        queryWrapper.eq("node_id", node_id);
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(name)) {
            queryWrapper.like("label", name);
        }
        labelMapper.selectPage(pageInfo, queryWrapper);
        List<LabelInfo> records = pageInfo.getRecords();
        KnowledgeInfo knowledgeInfo = knowledgeListMapper.selectById(node_id);
        for (LabelInfo label : records) {
            Map<String, Object> map = new HashMap<>();
            QueryWrapper<LabelPropertyInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("label_id", label.getId());
            List<LabelPropertyInfo> list = propertyMapper.selectList(wrapper);
            for (LabelPropertyInfo pro : list) {
                map.put(pro.getName(), pro.getProId());
            }
            label.setAttrs(map);
            label.setKnowledgeName(knowledgeInfo.getName());
        }
        return pageInfo;
    }
}